package test.algorithm.FastSlowPointer;

/**
 * 线索二叉树
 * @author serenity
 *
 */
public class BiThrTree {
	
	enum PointerTag{
		link,
		thread;
	}
	
	static class BiThrNode{
		char data;
		BiThrNode lChild;
		BiThrNode rChild;
		PointerTag lTag;
		PointerTag rTag;
		
	}
	
	
	/**
	 * 创建线索二叉树（接受先序遍历数组）
	 * @param data
	 */
	static BiThrNode createBiThrTree(char[] data){
		BiThrNode T = null;
		if(num<0 || num>=data.length){
			//已完成读取树的先序遍历数组
		}else if(' ' == data[num]){
			//父节点是叶子节点，子节点设置为null;
			T = null;
		}else{
			T = new BiThrNode();
			T.data = data[num];
			T.lTag = PointerTag.link;
			T.rTag = PointerTag.link;
			
			
			// 读取游标+1，递归创建左子树
			num++;
			T.lChild = createBiThrTree(data);
			
			// 读取游标+1，递归创建右子树
			num++;
			T.rChild = createBiThrTree(data);
			
			
		}
		return T;
	}
	
	/**
	 * 中序线索化
	 * @param root
	 */
	static void InThreading(BiThrNode root){
		if(root==null){
			return ;
		}
		
		//递归线索左子树
		InThreading(root.lChild);
		
		//当前节点前驱线索化
		if(root.lChild==null){
			root.lTag = PointerTag.thread;
			root.lChild = pre;
		}
		
		//前驱节点后继线索化
		if(pre.rChild==null){
			pre.rTag = PointerTag.thread;
			pre.rChild = root;
		}
		
		//前驱节点指向当前节点，继续递归执行线索化
		pre = root;
		
		//递归线索右子树
		InThreading(root.rChild);
	}
	
	/**
	 * 中序遍历线索化
	 * @param root
	 */
	static BiThrNode InOrderThreading(BiThrNode root){
		
		//创建头结点（中序遍历序列中第一个节点前驱线索指向头结点，最后一个节点后继线索也指向头结点）
		BiThrNode header = new BiThrNode();
		header.lTag = PointerTag.link;
		header.rTag = PointerTag.thread;
		//右指针回指
		header.rChild = header;
		
		if(root==null){
			header.lChild = header;
		}else{
			header.lChild = root;
			// 前驱节点指向头节点（线索有头节点开始）
			pre = header;
			InThreading(root);
			
			//最后一个节点后继线索化，指向头结点
			pre.rChild = header;
			pre.rTag = PointerTag.thread;
			header.rChild = pre;
		}
		
		return header;
	}
	
	/**
	 * 中序遍历二叉树，递归
	 * @param root
	 */
	static void InOrderTraverse(BiThrNode root){
		
		if(root!=null){
		
			if(root.lTag==PointerTag.link){
				InOrderTraverse(root.lChild);
			}
			
			System.out.print(root.data+" ");
			
			if(root.rTag==PointerTag.link){
				InOrderTraverse(root.rChild);
			}
		}
	}
	
	/**
	 * 中序遍历二叉树,利用中序线索遍历
	 * @param root
	 */
	static void InOrderTraverse2(BiThrNode root){
		if(root==null){
			return ;
		}
		BiThrNode node =root.lChild;
		while(node!=root){
			//找到左子树
			while(node.lTag==PointerTag.link){
				node = node.lChild;
			}
			
			//打印节点值
			System.out.print(node.data+" ");
			
			//左子树已打印，如果该节点右子树为空，找后继节点打印(左子树的父节点)
			while(node.rTag==PointerTag.thread && node.rChild!=root){
				node = node.rChild;
				System.out.print(node.data+" ");
			}
			
			//找父节点的右子树循环
			node = node.rChild;
		}
	}
	
	// 先序遍历序列当前读取位置
	static int num = 0;
	
	// 保存前驱节点，便于节点的前驱线索化
	static BiThrNode pre = null;
	
	/**
	 * 树  
	 *         A
	 *        / \
	 *       B   E
	 *      / \   \
	 *     C   D   F 
	 * @param args
	 */
	public static void main(String[] args) {
		
		//先序遍历序列
		char[] data = {'A','B','C',' ',' ','D',' ',' ','E',' ','F',' ',' '}; 
		BiThrNode root =  createBiThrTree(data);
		System.out.println("创建二叉树完毕");
		
		BiThrNode header = InOrderThreading(root);
		System.out.println("中序线索化完毕");
		
		InOrderTraverse(root);
		System.out.println("递归中序遍历完毕");
		
		InOrderTraverse2(header);
		System.out.println("线索中序遍历完毕");
	}

}
